This is what BSEDs would look like, and what the results of a bootstrapping analysis would be, under the assumptions of a) a uniform size-abundance distribution (Uniform size-abundance) and b) a uniform size-energy (Uniform size-energy)distribution.
Using the Andrews LTER small mammal data for demonstration.
Load the Andrews data, generate BSED, and get summary variables:
andrews <- load_paper_data()[[1]]
head(andrews)
andrews_bsed <- andrews %>%
add_energy_sizeclass() %>%
make_bsed()
andrews_vars <- list(nind = nrow(andrews),
nsp = length(unique(andrews$individual_species_ids)),
min_size = min(andrews$individual_sizes),
max_size = max(andrews$individual_sizes),
nsize_classes = nrow(andrews_bsed),
size_classes = andrews_bsed$size_class,
total_energy = sum((andrews$individual_sizes)^(3/4)))
Illustrating the conditions
Bootstrap analysis
For each community, generate: - plot of real BSED, a sample from the USA sims, and the calculated USA - p value that real BSED is similar to samples - plot of real BSED, sample from the USE sims, calculated USE - p value
rm(list=ls())
communities <- load_paper_data()
communities_energy <- lapply(communities, add_energy_sizeclass)
real_bseds <- lapply(communities_energy, make_bsed)
real_bsed_plots <- lapply(real_bseds, plot_bsed)
unif_sa_bootstraps <- lapply(communities, draw_bootstrap_samples, assumption = "uniform_size_abund", nbootstraps = 10000)
pull_bsed <- function(bootstrap_results, which_one){
if(which_one == "first") {
this_one <- bootstrap_results$sampled_bseds[[1]]
} else if (which_one == "calculated") {
this_one <- bootstrap_results$calculated_bsed
}
return(this_one)
}
unif_sa_samples <- lapply(unif_sa_bootstraps, pull_bsed, which_one = "first")
unif_sa_samples_plots <- lapply(unif_sa_samples, plot_bsed)
unif_sa_calculated <- lapply(unif_sa_bootstraps, pull_bsed, which_one = "calculated")
unif_sa_calculated_plots <- lapply(unif_sa_calculated, plot_bsed)
unif_sa_dois <- lapply(unif_sa_bootstraps, calculate_bootstrap_uniform_dois)
unif_sa_pvals <- lapply(unif_sa_dois, calculate_bootstrap_p)
sa_plots_list <- list()
for(i in 1:9) {
sa_plots_list[[i]] <- gridExtra::grid.arrange(real_bsed_plots[[i]], unif_sa_samples_plots[[i]], unif_sa_calculated_plots[[i]], nrow = 1)
print(names(communities)[[i]])
print(unif_sa_pvals[[i]])
invisible(sa_plots_list[[i]])
}
[1] "andrews"
[1] 0
[1] "niwot"
[1] 0
[1] "portal"
[1] 0
[1] "sev-5pgrass"
[1] 0
[1] "sev-5plarrea"
[1] 0
[1] "sev-goatdraw"
[1] 0
[1] "sev-rsgrass"
[1] 0
[1] "sev-rslarrea"
[1] 0
[1] "sev-two22"
[1] 0









rm(list=ls())
communities <- load_paper_data()
communities_energy <- lapply(communities, add_energy_sizeclass)
real_bseds <- lapply(communities_energy, make_bsed)
real_bsed_plots <- lapply(real_bseds, plot_bsed)
unif_se_bootstraps <- lapply(communities, draw_bootstrap_samples, assumption = "uniform_size_energy", nbootstraps = 10000)
pull_bsed <- function(bootstrap_results, which_one){
if(which_one == "first") {
this_one <- bootstrap_results$sampled_bseds[[1]]
} else if (which_one == "calculated") {
this_one <- bootstrap_results$calculated_bsed
}
return(this_one)
}
unif_se_samples <- lapply(unif_se_bootstraps, pull_bsed, which_one = "first")
unif_se_samples_plots <- lapply(unif_se_samples, plot_bsed)
unif_se_calculated <- lapply(unif_se_bootstraps, pull_bsed, which_one = "calculated")
unif_se_calculated_plots <- lapply(unif_se_calculated, plot_bsed)
unif_se_dois <- lapply(unif_se_bootstraps, calculate_bootstrap_uniform_dois)
unif_se_pvals <- lapply(unif_se_dois, calculate_bootstrap_p)
se_plots_list <- list()
for(i in 1:9) {
se_plots_list[[i]] <- gridExtra::grid.arrange(real_bsed_plots[[i]], unif_se_samples_plots[[i]], unif_se_calculated_plots[[i]], nrow = 1)
print(names(communities)[[i]])
print(unif_se_pvals[[i]])
invisible(se_plots_list[[i]])
}
[1] "andrews"
[1] 0.0014
[1] "niwot"
[1] 0
[1] "portal"
[1] 0
[1] "sev-5pgrass"
[1] 0
[1] "sev-5plarrea"
[1] 0
[1] "sev-goatdraw"
[1] 0
[1] "sev-rsgrass"
[1] 0
[1] "sev-rslarrea"
[1] 0
[1] "sev-two22"
[1] 8e-04









LS0tCnRpdGxlOiAiQlNFRCBzY2VuYXJpb3MiCmF1dGhvcjogIlJlbmF0YSBEaWF6IgpkYXRlOiAiNS8yOC8yMDE5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpsaWJyYXJ5KHJlcGxpY2F0ZWJlY3MpCmBgYAoKVGhpcyBpcyB3aGF0IEJTRURzIHdvdWxkIGxvb2sgbGlrZSwgYW5kIHdoYXQgdGhlIHJlc3VsdHMgb2YgYSBib290c3RyYXBwaW5nIGFuYWx5c2lzIHdvdWxkIGJlLCB1bmRlciB0aGUgYXNzdW1wdGlvbnMgb2YgYSkgYSB1bmlmb3JtIHNpemUtYWJ1bmRhbmNlIGRpc3RyaWJ1dGlvbiAoW1VuaWZvcm0gc2l6ZS1hYnVuZGFuY2VdKSBhbmQgYikgYSB1bmlmb3JtIHNpemUtZW5lcmd5IChbVW5pZm9ybSBzaXplLWVuZXJneV0pZGlzdHJpYnV0aW9uLiAKClVzaW5nIHRoZSBBbmRyZXdzIExURVIgc21hbGwgbWFtbWFsIGRhdGEgZm9yIGRlbW9uc3RyYXRpb24uCgpMb2FkIHRoZSBBbmRyZXdzIGRhdGEsIGdlbmVyYXRlIEJTRUQsIGFuZCBnZXQgc3VtbWFyeSB2YXJpYWJsZXM6CmBgYHtyIGxvYWQgYW5kcmV3c30KYW5kcmV3cyA8LSBsb2FkX3BhcGVyX2RhdGEoKVtbMV1dCmhlYWQoYW5kcmV3cykKCmFuZHJld3NfYnNlZCA8LSBhbmRyZXdzICU+JQogIGFkZF9lbmVyZ3lfc2l6ZWNsYXNzKCkgJT4lCiAgbWFrZV9ic2VkKCkKYGBgCgpgYGB7ciBhbmRyZXdzIGRlc2NyaXB0b3IgdmFyaWFibGVzfQphbmRyZXdzX3ZhcnMgPC0gbGlzdChuaW5kID0gbnJvdyhhbmRyZXdzKSwKICAgICAgICAgICAgICAgICAgICBuc3AgPSBsZW5ndGgodW5pcXVlKGFuZHJld3MkaW5kaXZpZHVhbF9zcGVjaWVzX2lkcykpLAogICAgICAgICAgICAgICAgICAgIG1pbl9zaXplID0gbWluKGFuZHJld3MkaW5kaXZpZHVhbF9zaXplcyksCiAgICAgICAgICAgICAgICAgICAgbWF4X3NpemUgPSBtYXgoYW5kcmV3cyRpbmRpdmlkdWFsX3NpemVzKSwKICAgICAgICAgICAgICAgICAgICBuc2l6ZV9jbGFzc2VzID0gbnJvdyhhbmRyZXdzX2JzZWQpLAogICAgICAgICAgICAgICAgICAgIHNpemVfY2xhc3NlcyA9IGFuZHJld3NfYnNlZCRzaXplX2NsYXNzLAogICAgICAgICAgICAgICAgICAgIHRvdGFsX2VuZXJneSA9IHN1bSgoYW5kcmV3cyRpbmRpdmlkdWFsX3NpemVzKV4oMy80KSkpCmBgYAoKIyMgSWxsdXN0cmF0aW5nIHRoZSBjb25kaXRpb25zCgojIyMgVW5pZm9ybSBzaXplLWFidW5kYW5jZQoKRm9yIGEgdW5pZm9ybSBzaXplLWFidW5kYW5jZSBkaXN0cmlidXRpb24sIGluZGl2aWR1YWxzJyBzaXplcyBhcmUgdW5pZm9ybWx5IGRpc3RyaWJ1dGVkIGZyb20gdGhlIG1pbmltdW0gdG8gdGhlIG1heGltdW0gYm9keSBzaXplIGluIHRoZSBjb21tdW5pdHkuCgpGb3Igc2ltdWxhdGlvbiwgdGhpcyB0cmFuc2xhdGVzIGFzOgoKYGBge3IgdW5pZm9ybSBzaXplIGFidW5kIHNhbXBsaW5nfQp1bmlmX3NhX3NhbXBsZSA8LSBydW5pZihuID0gYW5kcmV3c192YXJzJG5pbmQsIG1pbiA9IGFuZHJld3NfdmFycyRtaW5fc2l6ZSwgbWF4ID0gYW5kcmV3c192YXJzJG1heF9zaXplKQpgYGAKCldlIHVzZSB0aGlzIHZlY3RvciBvZiBtYXNzZXMgdG8gZ2VuZXJhdGUgYSBCU0VEIGZvciB0aGUgc2ltdWxhdGVkIGNvbW11bml0eToKCmBgYHtyIHVuaWYgc2l6ZSBhYnVuZCBic2VkfQp1bmlmX3NhX2JzZWQgPC0gYW5kcmV3cyAlPiUKICBkcGx5cjo6bXV0YXRlKGluZGl2aWR1YWxfc2l6ZXMgPSB1bmlmX3NhX3NhbXBsZSkgJT4lICMgQ2hhbmdlIG1lYXN1cmVkIG1hc3NlcyB0byBzaW11bGF0ZWQgbWFzc2VzCiAgYWRkX2VuZXJneV9zaXplY2xhc3MoKSAlPiUKICBtYWtlX2JzZWQoKQoKaGVhZCh1bmlmX3NhX2JzZWQpCmBgYAoKVG8gZGVmaW5lIHRoZSAidHJ1ZSIgZm9ybSBvZiB0aGUgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gZGVmaW5lIGEgImNvbW11bml0eSIgd2l0aCBleGFjdGx5IG9uZSBpbmRpdmlkdWFsIG9mIGV2ZXJ5IHNpemUgZnJvbSB0aGUgbWluaW11bSB0byB0aGUgbWF4aW11bSBpbiB0aGUgY29tbXVuaXR5IGFuZCBnZW5lcmF0ZSB0aGUgY29ycmVzcG9uZGluZyBCU0VELiBgcmVwbGljYXRlYmVjczo6Y2FsY3VsYXRlX3VuaWZvcm1fc2l6ZV9hYnVuZF9ic2VkYCBkb2VzIHRoaXMuIAoKYGBge3IgY2FsY3VsYXRlIHVuaWYgc2l6ZSBhYnVuZCBic2VkfQp1bmlmX3NhX2NhbGN1bGF0ZWQgPC0gY2FsY3VsYXRlX3VuaWZvcm1fc2l6ZV9hYnVuZF9ic2VkKGFuZHJld3MpCmBgYAoKCmBgYHtyIHBsb3QgdW5pZiBzaXplIGFidW5kIGJzZWRzLCBmaWcud2lkdGggPSAxNSwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQphbmRyZXdzX3Bsb3QgPSBwbG90X2JzZWQoYW5kcmV3c19ic2VkLCBic2VkX25hbWUgPSAiUmVhbCBBbmRyZXdzIikKCnVuaWZfc2Ffc2FtcGxlZF9wbG90ID0gcGxvdF9ic2VkKHVuaWZfc2FfYnNlZCwgYnNlZF9uYW1lID0gIlNhbXBsZWQgdW5pZm9ybSBzaXplLWFidW5kYW5jZSIpCgp1bmlmX3NhX2NhbGNfcGxvdCA9IHBsb3RfYnNlZCh1bmlmX3NhX2NhbGN1bGF0ZWQsIGJzZWRfbmFtZSA9ICInVHJ1ZScgdW5pZm9ybSBzaXplLWFidW5kYW5jZSIpCgp1bmlmX3NhX3Bsb3RzID0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoYW5kcmV3c19wbG90LCB1bmlmX3NhX3NhbXBsZWRfcGxvdCwgdW5pZl9zYV9jYWxjX3Bsb3QsIG5yb3cgPSAxKQoKaW52aXNpYmxlKHVuaWZfc2FfcGxvdHMpCgpgYGAKCgojIyMgVW5pZm9ybSBzaXplLWVuZXJneQoKRm9yIGEgdW5pZm9ybSBzaXplLWVuZXJneSBkaXN0cmlidXRpb24sIGFsbCBib2R5IHNpemUgY2xhc3NlcyBoYXZlIGFuIGVxdWFsIHNoYXJlIG9mIHRoZSBlbmVyZ3kgdXNlIGluIHRoZSBjb21tdW5pdHkuCgpUaGlzIGNvcnJlc3BvbmRzIHRvIGEgc3RlZXBseSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaXplIGFuZCBhYnVuZGFuY2UgYmVjYXVzZSBhKSBsYXJnZXIgaW5kaXZpZHVhbHMgdXNlIG1vcmUgZW5lcmd5IHBlciBjYXBpdGEgYW5kIGIpIHRoZSBib2R5IHNpemUgY2xhc3NlcyBhcmUgYmlubmVkIGluIGxvZyB1bml0cywgc28gdGhlIGxhcmdlciBib2R5IHNpemUgY2xhc3NlcyBoYXZlIHRoZSBzYW1lIGFtb3VudCBvZiBlbmVyZ3kgZGl2aWRlZCBhY3Jvc3MgYSBicm9hZGVyIHBvcnRpb24gb2YgdGhlIHNpemUgc3BlY3RydW0uIAoKVG8gc2FtcGxlOgoKYGBge3IgdW5pZm9ybSBzaXplIGVuZXJneSBzYW1wbGV9Cgp1bmlmX3NlX2JzZWQgPC0gYW5kcmV3c19ic2VkICU+JQogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5ID0gcnVuaWYobiA9IGFuZHJld3NfdmFycyRuc2l6ZV9jbGFzc2VzLCBtaW4gPSAwLCBtYXggPSBhbmRyZXdzX3ZhcnMkdG90YWxfZW5lcmd5KSkgJT4lICMgdGhlIG1heGltdW0gZG9lc24ndCBtYXR0ZXIsIGJlY2F1c2Ugd2Ugd2lsbCBjb252ZXJ0IGl0IHRvIHByb3BvcnRpb25hbAogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5X3Byb3BvcnRpb25hbCA9IHRvdGFsX2VuZXJneSAvIHN1bSh0b3RhbF9lbmVyZ3kpKQoKYGBgCgoKVG8gY2FsY3VsYXRlOgoKYGBge3IgdW5pZm9ybSBzaXplIGVuZXJneSBjYWxjdWxhdGlvbn0KdW5pZl9zZV9jYWxjdWxhdGVkID0gYW5kcmV3c19ic2VkICU+JQogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5X3Byb3BvcnRpb25hbCA9IDEvYW5kcmV3c192YXJzJG5zaXplX2NsYXNzZXMpCmBgYAoKCmBgYHtyIHBsb3QgdW5pZiBzaXplIGVuZXJneSBic2VkcywgZmlnLndpZHRoID0gMTUsIGZpZy5oZWlnaHQgPSA1LCBlY2hvID0gRn0KYW5kcmV3c19wbG90ID0gcGxvdF9ic2VkKGFuZHJld3NfYnNlZCwgYnNlZF9uYW1lID0gIlJlYWwgQW5kcmV3cyIpCgp1bmlmX3NlX3NhbXBsZWRfcGxvdCA9IHBsb3RfYnNlZCh1bmlmX3NlX2JzZWQsIGJzZWRfbmFtZSA9ICJTYW1wbGVkIHVuaWZvcm0gc2l6ZS1lbmVyZ3kiKQoKdW5pZl9zZV9jYWxjX3Bsb3QgPSBwbG90X2JzZWQodW5pZl9zZV9jYWxjdWxhdGVkLCBic2VkX25hbWUgPSAiJ1RydWUnIHVuaWZvcm0gc2l6ZS1lbmVyZ3kiKQoKdW5pZl9zZV9wbG90cyA9IGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKGFuZHJld3NfcGxvdCwgdW5pZl9zZV9zYW1wbGVkX3Bsb3QsIHVuaWZfc2VfY2FsY19wbG90LCBucm93ID0gMSkKCmludmlzaWJsZSh1bmlmX3NlX3Bsb3RzKQoKYGBgCgojIyBCb290c3RyYXAgYW5hbHlzaXMKCkZvciBlYWNoIGNvbW11bml0eSwgZ2VuZXJhdGU6Ci0gcGxvdCBvZiByZWFsIEJTRUQsIGEgc2FtcGxlIGZyb20gdGhlIFVTQSBzaW1zLCBhbmQgdGhlIGNhbGN1bGF0ZWQgVVNBIAotIHAgdmFsdWUgdGhhdCByZWFsIEJTRUQgaXMgc2ltaWxhciB0byBzYW1wbGVzCi0gcGxvdCBvZiByZWFsIEJTRUQsIHNhbXBsZSBmcm9tIHRoZSBVU0Ugc2ltcywgY2FsY3VsYXRlZCBVU0UKLSBwIHZhbHVlIAoKYGBge3Igc2l6ZSBhYnVuZGFuY2UgYm9vdHN0cmFwfQpybShsaXN0PWxzKCkpCmNvbW11bml0aWVzIDwtIGxvYWRfcGFwZXJfZGF0YSgpCgpjb21tdW5pdGllc19lbmVyZ3kgPC0gbGFwcGx5KGNvbW11bml0aWVzLCBhZGRfZW5lcmd5X3NpemVjbGFzcykKCnJlYWxfYnNlZHMgPC0gbGFwcGx5KGNvbW11bml0aWVzX2VuZXJneSwgbWFrZV9ic2VkKQoKcmVhbF9ic2VkX3Bsb3RzIDwtIGxhcHBseShyZWFsX2JzZWRzLCBwbG90X2JzZWQpCgp1bmlmX3NhX2Jvb3RzdHJhcHMgPC0gbGFwcGx5KGNvbW11bml0aWVzLCBkcmF3X2Jvb3RzdHJhcF9zYW1wbGVzLCBhc3N1bXB0aW9uID0gInVuaWZvcm1fc2l6ZV9hYnVuZCIsIG5ib290c3RyYXBzID0gMTAwMDApCgpwdWxsX2JzZWQgPC0gZnVuY3Rpb24oYm9vdHN0cmFwX3Jlc3VsdHMsIHdoaWNoX29uZSl7CiAgaWYod2hpY2hfb25lID09ICJmaXJzdCIpIHsKICB0aGlzX29uZSA8LSBib290c3RyYXBfcmVzdWx0cyRzYW1wbGVkX2JzZWRzW1sxXV0KICB9IGVsc2UgaWYgKHdoaWNoX29uZSA9PSAiY2FsY3VsYXRlZCIpIHsKICAgIHRoaXNfb25lIDwtIGJvb3RzdHJhcF9yZXN1bHRzJGNhbGN1bGF0ZWRfYnNlZAogIH0KICByZXR1cm4odGhpc19vbmUpCn0KCnVuaWZfc2Ffc2FtcGxlcyA8LSBsYXBwbHkodW5pZl9zYV9ib290c3RyYXBzLCBwdWxsX2JzZWQsIHdoaWNoX29uZSA9ICJmaXJzdCIpCgp1bmlmX3NhX3NhbXBsZXNfcGxvdHMgPC0gbGFwcGx5KHVuaWZfc2Ffc2FtcGxlcywgcGxvdF9ic2VkKQoKdW5pZl9zYV9jYWxjdWxhdGVkIDwtIGxhcHBseSh1bmlmX3NhX2Jvb3RzdHJhcHMsIHB1bGxfYnNlZCwgd2hpY2hfb25lID0gImNhbGN1bGF0ZWQiKQoKdW5pZl9zYV9jYWxjdWxhdGVkX3Bsb3RzIDwtIGxhcHBseSh1bmlmX3NhX2NhbGN1bGF0ZWQsIHBsb3RfYnNlZCkKCnVuaWZfc2FfZG9pcyA8LSAgbGFwcGx5KHVuaWZfc2FfYm9vdHN0cmFwcywgY2FsY3VsYXRlX2Jvb3RzdHJhcF91bmlmb3JtX2RvaXMpCgp1bmlmX3NhX3B2YWxzIDwtIGxhcHBseSh1bmlmX3NhX2RvaXMsIGNhbGN1bGF0ZV9ib290c3RyYXBfcCkKCmBgYAoKYGBge3Igc2l6ZSBhYnVuZGFuY2UgcGxvdHMsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gNX0Kc2FfcGxvdHNfbGlzdCA8LSBsaXN0KCkKCmZvcihpIGluIDE6OSkgewpzYV9wbG90c19saXN0W1tpXV0gPC0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocmVhbF9ic2VkX3Bsb3RzW1tpXV0sIHVuaWZfc2Ffc2FtcGxlc19wbG90c1tbaV1dLCB1bmlmX3NhX2NhbGN1bGF0ZWRfcGxvdHNbW2ldXSwgbnJvdyA9IDEpCgpwcmludChuYW1lcyhjb21tdW5pdGllcylbW2ldXSkKcHJpbnQodW5pZl9zYV9wdmFsc1tbaV1dKQppbnZpc2libGUoc2FfcGxvdHNfbGlzdFtbaV1dKQoKfQoKYGBgCgpgYGB7ciBzaXplIGVuZXJneSBib290c3RyYXB9CnJtKGxpc3Q9bHMoKSkKY29tbXVuaXRpZXMgPC0gbG9hZF9wYXBlcl9kYXRhKCkKCmNvbW11bml0aWVzX2VuZXJneSA8LSBsYXBwbHkoY29tbXVuaXRpZXMsIGFkZF9lbmVyZ3lfc2l6ZWNsYXNzKQoKcmVhbF9ic2VkcyA8LSBsYXBwbHkoY29tbXVuaXRpZXNfZW5lcmd5LCBtYWtlX2JzZWQpCgpyZWFsX2JzZWRfcGxvdHMgPC0gbGFwcGx5KHJlYWxfYnNlZHMsIHBsb3RfYnNlZCkKCnVuaWZfc2VfYm9vdHN0cmFwcyA8LSBsYXBwbHkoY29tbXVuaXRpZXMsIGRyYXdfYm9vdHN0cmFwX3NhbXBsZXMsIGFzc3VtcHRpb24gPSAidW5pZm9ybV9zaXplX2VuZXJneSIsIG5ib290c3RyYXBzID0gMTAwMDApCgpwdWxsX2JzZWQgPC0gZnVuY3Rpb24oYm9vdHN0cmFwX3Jlc3VsdHMsIHdoaWNoX29uZSl7CiAgaWYod2hpY2hfb25lID09ICJmaXJzdCIpIHsKICB0aGlzX29uZSA8LSBib290c3RyYXBfcmVzdWx0cyRzYW1wbGVkX2JzZWRzW1sxXV0KICB9IGVsc2UgaWYgKHdoaWNoX29uZSA9PSAiY2FsY3VsYXRlZCIpIHsKICAgIHRoaXNfb25lIDwtIGJvb3RzdHJhcF9yZXN1bHRzJGNhbGN1bGF0ZWRfYnNlZAogIH0KICByZXR1cm4odGhpc19vbmUpCn0KCnVuaWZfc2Vfc2FtcGxlcyA8LSBsYXBwbHkodW5pZl9zZV9ib290c3RyYXBzLCBwdWxsX2JzZWQsIHdoaWNoX29uZSA9ICJmaXJzdCIpCgp1bmlmX3NlX3NhbXBsZXNfcGxvdHMgPC0gbGFwcGx5KHVuaWZfc2Vfc2FtcGxlcywgcGxvdF9ic2VkKQoKdW5pZl9zZV9jYWxjdWxhdGVkIDwtIGxhcHBseSh1bmlmX3NlX2Jvb3RzdHJhcHMsIHB1bGxfYnNlZCwgd2hpY2hfb25lID0gImNhbGN1bGF0ZWQiKQoKdW5pZl9zZV9jYWxjdWxhdGVkX3Bsb3RzIDwtIGxhcHBseSh1bmlmX3NlX2NhbGN1bGF0ZWQsIHBsb3RfYnNlZCkKCnVuaWZfc2VfZG9pcyA8LSAgbGFwcGx5KHVuaWZfc2VfYm9vdHN0cmFwcywgY2FsY3VsYXRlX2Jvb3RzdHJhcF91bmlmb3JtX2RvaXMpCgp1bmlmX3NlX3B2YWxzIDwtIGxhcHBseSh1bmlmX3NlX2RvaXMsIGNhbGN1bGF0ZV9ib290c3RyYXBfcCkKCmBgYAoKYGBge3Igc2l6ZSBlbmVyZ3kgcGxvdHMsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gNX0Kc2VfcGxvdHNfbGlzdCA8LSBsaXN0KCkKCmZvcihpIGluIDE6OSkgewpzZV9wbG90c19saXN0W1tpXV0gPC0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocmVhbF9ic2VkX3Bsb3RzW1tpXV0sIHVuaWZfc2Vfc2FtcGxlc19wbG90c1tbaV1dLCB1bmlmX3NlX2NhbGN1bGF0ZWRfcGxvdHNbW2ldXSwgbnJvdyA9IDEpCgpwcmludChuYW1lcyhjb21tdW5pdGllcylbW2ldXSkKcHJpbnQodW5pZl9zZV9wdmFsc1tbaV1dKQppbnZpc2libGUoc2VfcGxvdHNfbGlzdFtbaV1dKQoKfQoKYGBg